﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KNXFramework.KNXObjects;
using KNXLibrary.Enum;
using KNXLibrary.Addresses;

namespace KNXFramework
{
    public class ObjectController : IDictionary<string, KNXObjectBase>
    {
        private Dictionary<string, KNXObjectBase> m_KNXObjects = new Dictionary<string, KNXObjectBase>();
        public delegate void KNXObjectUpdateEventHandler(string id, string newValue);
        public event KNXObjectUpdateEventHandler OnKNXObjectUpdate;
        
        public void AddNewObject(KNXObjectBase obj)
        {
            if (!ContainsKey(obj.ID))
            {
                Add(obj.ID, obj);
            }
            else
                throw new ApplicationException("An object with the same ID already exists");
        }

        private KNXConnection m_KNXConnection;

        public KNXConnection KNXConnection
        {
            get { return m_KNXConnection; }
            set
            {
                this.m_KNXConnection = value;
                if (m_KNXConnection != null)
                {
                    m_KNXConnection.OnResponse += new KNXConnection.KNXDeletage(m_KNXConnection_OnResponse);
                    m_KNXConnection.OnRead += new KNXConnection.KNXDeletage(m_KNXConnection_OnRead);
                    m_KNXConnection.OnWrite += new KNXConnection.KNXDeletage(m_KNXConnection_OnWrite);
                }
            }
        }
        public ObjectController(KNXConnection knxConnection)
        {
            KNXConnection = knxConnection;
            KNXFramework.Settings.KNXSettings.LoadObjectsFromSettings(this);
        }

        void m_KNXConnection_OnWrite(PhysicalAddress src, GroupAddress dest, tuwien.auto.eibclient.EIBBuffer buffer)
        {
            foreach (KNXObjectBase obj in m_KNXObjects.Values)
            {
                if (obj.GAD == dest)
                {
                    if ((obj.Flags & FlagsEnum.Write) == FlagsEnum.Write 
                        && (obj.Flags & FlagsEnum.Communication) == FlagsEnum.Communication)
                    {
                        obj.WriteValue(src, buffer);
                    }                 
                }
            }
            
        }

        void m_KNXConnection_OnRead(PhysicalAddress src, GroupAddress dest, tuwien.auto.eibclient.EIBBuffer buffer)
        {            
            foreach (KNXObjectBase obj in m_KNXObjects.Values)
            {
                if (obj.GAD == dest)
                {
                    if ((obj.Flags & FlagsEnum.Update) == FlagsEnum.Update
                        && (obj.Flags & FlagsEnum.Communication) == FlagsEnum.Communication)
                    {
                        obj.SendValue(src, buffer);
                    }
                }
            }
            
        }

        void m_KNXConnection_OnResponse(PhysicalAddress src, GroupAddress dest, tuwien.auto.eibclient.EIBBuffer buffer)
        {
            foreach (KNXObjectBase obj in m_KNXObjects.Values)
            {
                if (obj.GAD == dest)
                {
                    if ((obj.Flags & FlagsEnum.Update) == FlagsEnum.Update
                        && (obj.Flags & FlagsEnum.Communication) == FlagsEnum.Communication)
                    {
                        obj.WriteValue(src, buffer);
                    }
                }
            }                        
        }



        #region IDictionary<string,KNXObjectBase> Members

        public void Add(string key, KNXObjectBase value)
        {
            m_KNXObjects.Add(key, value);
            value.OnUpdateEvent += new EventHandler(value_OnUpdateEvent);
        }

        void value_OnUpdateEvent(object sender, EventArgs e)
        {
            KNXObjectBase knxObject = sender as KNXObjectBase;
            if (knxObject != null && OnKNXObjectUpdate != null)
            {
                foreach (KNXObjectUpdateEventHandler handler in OnKNXObjectUpdate.GetInvocationList())
                {
                    handler(knxObject.ID, knxObject.GetValue());
                }
            }
        }

        public bool ContainsKey(string key)
        {
            return m_KNXObjects.ContainsKey(key);
        }

        public ICollection<string> Keys
        {
            get { return m_KNXObjects.Keys; }
        }

        public bool Remove(string key)
        {
            return m_KNXObjects.Remove(key);
        }

        public bool TryGetValue(string key, out KNXObjectBase value)
        {
            return m_KNXObjects.TryGetValue(key, out value);
        }

        public ICollection<KNXObjectBase> Values
        {
            get { return m_KNXObjects.Values; }
        }

        public KNXObjectBase this[string key]
        {
            get
            {
                return m_KNXObjects[key];
            }
            set
            {
                m_KNXObjects[key] = value;
            }
        }

        #endregion

        #region ICollection<KeyValuePair<string,KNXObjectBase>> Members

        public void Add(KeyValuePair<string, KNXObjectBase> item)
        {
            throw new NotImplementedException();
        }

        public void Clear()
        {
            throw new NotImplementedException();
        }

        public bool Contains(KeyValuePair<string, KNXObjectBase> item)
        {
            throw new NotImplementedException();
        }

        public void CopyTo(KeyValuePair<string, KNXObjectBase>[] array, int arrayIndex)
        {
            throw new NotImplementedException();
        }

        public int Count
        {
            get { return m_KNXObjects.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(KeyValuePair<string, KNXObjectBase> item)
        {
            return m_KNXObjects.Remove(item.Key);
        }

        #endregion

        #region IEnumerable<KeyValuePair<string,KNXObjectBase>> Members

        public IEnumerator<KeyValuePair<string, KNXObjectBase>> GetEnumerator()
        {
            return m_KNXObjects.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return m_KNXObjects.GetEnumerator();
        }

        #endregion
    }
}
